#include <QDebug>
#include <QtOpenGL>
#include <QPoint>
#include <QFileDialog>

#include "rendercontroller.h"
#include "GLDisplay.h"
#include "mainwindow.h"
#include "Object3D.h"
#include "cubo.h"
#include "sphere.h"
#include "cone.h"
#include "Arcball.h"
#include "DirectionalLight.h"

RenderController::RenderController(MainWindow *mainWindow,
                                   QObject *parent):
    QObject(parent)
{
    light = new DirectionalLight;
    arcBall = new ArcBall(500);
    wireframe = false;
    lightRotation = false;
    tipoObjeto = 0;

    this->display = new GLDisplay();
    mainWindow->setGLDisplay(display);

    {

       // esta ordem deve ser mantida
        display->updateGL();

        sphere = new Sphere();
        sphere->setColor(255, 255, 255);
        sphere->setTraslation(QVector3D(-3.0, 0.0, 0.0));
        sphere->setEscala(0.5, 0.5, 0.5);
        sphere->draw();
       // model = sphere;

        cubo = new Cubo();
        cubo->setColor(255, 255, 255);
        cubo->setTraslation(QVector3D(3.0, 0.0, 0.0));
        cubo->setEscala(0.5, 0.5, 0.5);
        cubo->draw();
        cubo->setShader(false);

        cone = new Cone();
        cone->setColor(255, 255, 255);
        cone->setTraslation(QVector3D(0.0, 0.0, 0.0));
        cone->setEscala(0.5, 0.5, 0.5);
        cone->draw();



        connect(display, SIGNAL(drawModel()),
                this, SLOT(drawModel(
                               )));

        connect(display, SIGNAL(lightSetup()),
                this, SLOT(lightSetup()));
    }

    connect(display, SIGNAL(mouseLefthFinish(QPoint,QPoint)),
            this, SLOT(mouseLefthFinish(QPoint,QPoint)));

    connect(display, SIGNAL(mouseLeftMove(QPoint,QPoint)),
            this, SLOT(mouseLeftMove(QPoint,QPoint)));

    connect(display, SIGNAL(mouseRigthFinish(QPoint,QPoint)),
            this, SLOT(mouseRigthFinish(QPoint,QPoint)));

    connect(display, SIGNAL(mouseRigthMove(QPoint,QPoint)),
            this, SLOT(mouseRigthMove(QPoint,QPoint)));

    connect(display, SIGNAL(mouseCancel()),
            this, SLOT(mouseCancel()));

    connect(display, SIGNAL(mouseRightClick(QPoint)),
            this, SLOT(mouseRigthClick(QPoint)));

    connect(mainWindow, SIGNAL(wireframeClicked(bool)),
            this, SLOT(wireFrameToggle(bool)));

    connect(mainWindow, SIGNAL(saveResultAsImage()),
            this, SLOT(saveResultAsImage()));

    connect(mainWindow, SIGNAL(lightRotationToggle(bool)),
            this, SLOT(lightRotationToggle(bool)));

    connect(mainWindow, SIGNAL(radioEvent(bool,bool,bool)),
            this, SLOT(radioEvent(bool,bool,bool)));

    connect(mainWindow, SIGNAL(aplicaCores(int,int,int)),
            this ,SLOT(aplicaCores(int,int,int)));

    connect(mainWindow, SIGNAL(aplicaEscalas(float,float,float)),
            this ,SLOT(aplicaEscalas(float,float,float)));

    connect(mainWindow, SIGNAL(aplicaTranslacoes(double,double,double)),
            this ,SLOT(aplicaTranslacoes(double,double,double)));

    connect(mainWindow, SIGNAL(aplicaCamera(double,double)),
            this ,SLOT(aplicaCamera(double,double)));

    connect(mainWindow, SIGNAL(shaderLigado(bool)),
            this, SLOT(shaderLigado(bool)));

    mainWindow->show();

}

RenderController::~RenderController()
{
    delete cubo;
    delete cone;
    delete sphere;
    delete display;
    delete arcBall;
}

void RenderController::updateGL(void)
{
    display->updateGL();
}

void RenderController::lightSetup(void)
{
    light->draw();
}
void RenderController::aplicaCores(int red,int green,int blue)
{
     qDebug() << "red passado +++ " << red;
     qDebug() << "green passado +++ " << green;
     qDebug() << "blue passado +++ " << blue;
//cubo->setColor();
      model->setColor(red,green,blue);
    // model->

     display->updateGL();
}
void RenderController::aplicaCamera(double posX, double posY)
{
     qDebug() << "camera +++ " << posX;

     //display->setLookAt(model->center().x(),0);
     display->setLookAt(posX,posY);

     display->updateGL();
}
void RenderController::aplicaEscalas(float x,float y,float z)
{
     qDebug() << "x passado +++ " << x;
     qDebug() << "y passado +++ " << y;
     qDebug() << "z passado +++ " << z;
//cubo->setColor();
      model->setEscala(x,y,z);
    // model->

     display->updateGL();
}
void RenderController::aplicaTranslacoes(double x, double y, double z)
{
     qDebug() << "x trans +++ " << x;
     qDebug() << "y trans +++ " << y;
     qDebug() << "z trans +++ " << z;
//cubo->setColor();
      model->setTraslation(QVector3D(x,y,z));
    // model->

     display->updateGL();
}
//void RenderController::ShaderLigado(bool ligado){
 //   MostraShader = ligado;
//}

void RenderController::radioEvent(bool obj1,bool obj2,bool obj3)
{

   if(obj1)
    {
       tipoObjeto = 0;
    }
    if(obj2)
    {
        tipoObjeto = 1;
        //qDebug() << "passei aqui noixxx " << obj2;
       // display->setLookAt();

    }
    if(obj3)
    {
        tipoObjeto = 2;
        //qDebug() << "passei aqui noixxx " << obj2;
    }
    display->updateGL();

}
void RenderController::shaderLigado(bool ligado){
    model->setShader(ligado);
    display->updateGL();
}

void RenderController::drawModel()
{
    //this->model = objeto;
    if(wireframe)
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    else
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

     sphere->draw();
     cubo->draw();
     cone->draw();

   switch(tipoObjeto){
        case 0:

            model = sphere;
           // model->texture();
           // cone->setEscala(0,0,0);
           // display->updateGL();

            break;
        case 1:
            //cubo->draw();
            model = cubo;
         //   cone->setEscala(0,0,0);
           // display->updateGL();
         //    model->setEscala(1.5,1.5,1.5);
            break;
        case 2:
           // cone->draw();
            model = cone;
         //   cone->setEscala(0,0,-2);
           // display->updateGL();

          //   model->setEscala(1.5,1.5,1.5);
            break;
        }
}

void RenderController::mouseRigthMove(QPoint begin, QPoint curr)
{
    QVector3D v(curr-begin);
    model->setTraslation(v/40.0);
    display->updateGL();


}

void RenderController::mouseRigthFinish(QPoint ini, QPoint curr)
{
    QVector3D v(curr-ini);
    model->setTraslation(QVector3D());
    model->setCenter(model->center() + (v/40.0));
    display->updateGL();
}

void RenderController::mouseLeftMove(QPoint ini, QPoint curr)
{
    if(ini == curr)
        return;
    QPoint center(display->width()/2, display->height()/2);

    if(lightRotation)
        light->setInteractiveQuartenion(
                arcBall->rotationForPoints(center,curr, ini));
    else
        model->setInteractiveQuartenion(
                arcBall->rotationForPoints(center,curr, ini));

    display->updateGL();
}

void RenderController::mouseLefthFinish(QPoint ini, QPoint curr)
{
    if(ini == curr)
        return;
    QPoint center(display->width()/2, display->height()/2);
    QQuaternion t = arcBall->rotationForPoints(center,curr, ini);
    if(lightRotation)
    {
        light->addRotation(t);
        light->setInteractiveQuartenion(QQuaternion());
    }else
    {
        model->addRotation(t);
        model->setInteractiveQuartenion(QQuaternion());
    }

    display->updateGL();
}

void RenderController::mouseCancel()
{
    if(lightRotation)
        light->setInteractiveQuartenion(QQuaternion());
    else
        model->setInteractiveQuartenion(QQuaternion());

    display->updateGL();
}
void RenderController::mouseRightClick(QPoint curr)
{


    display->updateGL();
}
void RenderController::wireFrameToggle(bool wireframe)
{
    this->wireframe = wireframe;
    display->updateGL();
}

void RenderController::saveResultAsImage()
{
    QString filePath = saveImage();

    if(filePath.isEmpty())
        return;

    display->updateGL();
    display->grabFrameBuffer().save(filePath);
}

QGLWidget* RenderController::getGLContext(void)
{
    return display;
}

void RenderController::lightRotationToggle(bool lt)
{
    lightRotation = lt;
}

QVector3D RenderController::getLightPosition() const
{
    return light->getLightPosition();
}

QString RenderController::saveImage()
{
    static QString dir = ".";
    QString filename = QFileDialog::getSaveFileName(0,
                                                    "Save Image",
                                                    dir,
                                                    "*.png");
    QString ext = ".png";

    if(filename == ext || filename.isEmpty())
        return QString();

    QFileInfo fi(filename);
    dir = fi.absolutePath();

    if(filename.right(ext.length()) != ext)
        filename += ext;

    return filename;
}
